package com.config;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.exception.ApiException;
import com.web.controller.MedicalController;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cxt
 * @date 2022/3/31
 * <p>
 * 拦截验证身份
 */
public class AdminInterceptor implements HandlerInterceptor {
    private final JWTUtil util = new JWTUtil();

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 安全认真部分，获取token并验证
        // 先尝试在header获取，没有则再尝试从cookie中获取
        String token = request.getHeader("token");
        boolean isCookie = false;
        if (StringUtils.isEmpty(token)) {
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if (StringUtils.equals(cookie.getName(), "token")) {
                        token = cookie.getValue();
                        isCookie = true;
                        break;
                    }
                }
            }
        }

        if (token != null) {
            boolean verify = util.verify(token, MedicalController.SALT.getBytes());
            if (verify) {
                JWT jwt = util.parseToken(token); // 解析token
                Long createTime = (Long) jwt.getPayload("createTime");
                Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
                long l = milliSecond - createTime;
                if (l <= 600000) {
                    // 检查token是否将要过期，是则刷新一个token,前端也要判断token过期时候过来刷新token
                    if (l < 200000) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("userName", jwt.getPayload("userName"));
                        map.put("idcardNo", jwt.getPayload("idcardNo"));
                        long newMilli = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
                        map.put("createTime", newMilli);
                        String newToken = JWTUtil.createToken(map, MedicalController.SALT.getBytes());

                        if (isCookie) {
                            Cookie cookie = new Cookie("token", newToken);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                        // TODO 和前端约定，新token名
                        response.addHeader("New-Token", newToken);
                    }
                    return true;
                }
            }
        }
        throw new ApiException(ApiException.E_UNAUTHORIZED);
    }

    /**
     * 在整个请求结束之后被调用，也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//        System.out.println("执行了TestInterceptor的afterCompletion方法");
    }
}
